﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Linq;

namespace Gmantis.Controls.DataGrid
{
    public enum PagerDisplayMode
    {
        FirstLastNumeric,
        FirstLastPreviousNext,
        FirstLastPreviousNextNumeric,
        Numeric,
        PreviousNext,
        PreviousNextNumeric
    }

    [TemplatePart(Name = "CurrentPageSuffixTextBlock", Type = typeof(TextBlock)), 
    TemplateVisualState(Name = "FirstLastPreviousNext", GroupName = "DisplayModeStates"), 
    TemplateVisualState(Name = "Numeric", GroupName = "DisplayModeStates"), 
    TemplateVisualState(Name = "PreviousNext", GroupName = "DisplayModeStates"), 
    TemplateVisualState(Name = "PreviousNextNumeric", GroupName = "DisplayModeStates"), 
    StyleTypedProperty(Property = "NumericButtonStyle", StyleTargetType = typeof(ToggleButton)), 
    TemplatePart(Name = "PreviousPageButton", Type = typeof(ButtonBase)), 
    TemplatePart(Name = "CurrentPagePrefixTextBlock", Type = typeof(TextBlock)), 
    TemplatePart(Name = "CurrentPageTextBox", Type = typeof(TextBox)), 
    TemplatePart(Name = "NextPageButton", Type = typeof(ButtonBase)), 
    TemplateVisualState(Name = "MoveDisabled", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "MoveFirstEnabled", GroupName = "MoveFirstStates"), 
    TemplateVisualState(Name = "FirstLastNumeric", GroupName = "DisplayModeStates"), 
    TemplateVisualState(Name = "FirstLastPreviousNextNumeric", GroupName = "DisplayModeStates"), 
    TemplatePart(Name = "LastPageButton", Type = typeof(ButtonBase)), 
    TemplatePart(Name = "NumericButtonPanel", Type = typeof(Panel)), 
    TemplateVisualState(Name = "Normal", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Disabled", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "MoveEnabled", GroupName = "CommonStates"), 
    TemplatePart(Name = "FirstPageButton", Type = typeof(ButtonBase)), 
    TemplateVisualState(Name = "MoveFirstDisabled", GroupName = "MoveFirstStates"), 
    TemplateVisualState(Name = "MovePreviousEnabled", GroupName = "MovePreviousStates"), 
    TemplateVisualState(Name = "MovePreviousDisabled", GroupName = "MovePreviousStates"), 
    TemplateVisualState(Name = "MoveNextEnabled", GroupName = "MoveNextStates"), 
    TemplateVisualState(Name = "MoveNextDisabled", GroupName = "MoveNextStates"), 
    TemplateVisualState(Name = "MoveLastEnabled", GroupName = "MoveLastStates"), 
    TemplateVisualState(Name = "MoveLastDisabled", GroupName = "MoveLastStates"), 
    TemplateVisualState(Name = "TotalPageCountKnown", GroupName = "TotalPageCountKnownStates"), 
    TemplateVisualState(Name = "TotalPageCountUnknown", GroupName = "TotalPageCountKnownStates")]
    public class DataPager : Control
    {
        // Fields
        private TextBlock _currentPagePrefixTextBlock;
        private TextBlock _currentPageSuffixTextBlock;
        private TextBox _currentPageTextBox;
        private ButtonBase _firstPageButtonBase;
        private int _focusedToggleButtonIndex = -1;
        private bool _ignoreToggleButtonCheckedNotification;
        private bool _ignoreToggleButtonFocusNotification;
        private bool _ignoreToggleButtonUncheckedNotification;
        private ButtonBase _lastPageButtonBase;
        private bool _needPageChangingNotification = true;
        private ButtonBase _nextPageButtonBase;
        private Panel _numericButtonPanel;
        private ButtonBase _previousPageButtonBase;
        private int _requestedPageIndex;
        private WeakEventListener<DataPager, object, PropertyChangedEventArgs> _weakEventListenerPropertyChanged;
        public static readonly DependencyProperty AutoEllipsisProperty = DependencyProperty.Register("AutoEllipsis", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnAutoEllipsisPropertyChanged)));
        public static readonly DependencyProperty CanChangePageProperty = DependencyProperty.Register("CanChangePage", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty CanMoveToFirstPageProperty = DependencyProperty.Register("CanMoveToFirstPage", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty CanMoveToLastPageProperty = DependencyProperty.Register("CanMoveToLastPage", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty CanMoveToNextPageProperty = DependencyProperty.Register("CanMoveToNextPage", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty CanMoveToPreviousPageProperty = DependencyProperty.Register("CanMoveToPreviousPage", typeof(bool), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(DataPager), new PropertyMetadata(new CornerRadius()));
        private const string DATAPAGER_currentPageTextBoxAutomationId = "CurrentPage";
        private const PagerDisplayMode DATAPAGER_defaultDisplayMode = PagerDisplayMode.FirstLastPreviousNext;
        private const int DATAPAGER_defaultNumericButtonCount = 5;
        private const int DATAPAGER_defaultPageIndex = -1;
        private const string DATAPAGER_elementCurrentPagePrefixTextBlockn = "CurrentPagePrefixTextBlock";
        private const string DATAPAGER_elementCurrentPageSuffixTextBlock = "CurrentPageSuffixTextBlock";
        private const string DATAPAGER_elementCurrentPageTextBox = "CurrentPageTextBox";
        private const string DATAPAGER_elementFirstPageButton = "FirstPageButton";
        private const string DATAPAGER_elementLastPageButton = "LastPageButton";
        private const string DATAPAGER_elementNextPageButton = "NextPageButton";
        private const string DATAPAGER_elementNumericButtonPanel = "NumericButtonPanel";
        private const string DATAPAGER_elementPreviousPageButton = "PreviousPageButton";
        private const string DATAPAGER_firstPageButtonAutomationId = "LargeDecrement";
        private const string DATAPAGER_groupCommon = "CommonStates";
        private const string DATAPAGER_groupDisplayMode = "DisplayModeStates";
        private const string DATAPAGER_groupMove = "MoveStates";
        private const string DATAPAGER_groupMoveFirst = "MoveFirstStates";
        private const string DATAPAGER_groupMoveLast = "MoveLastStates";
        private const string DATAPAGER_groupMoveNext = "MoveNextStates";
        private const string DATAPAGER_groupMovePrevious = "MovePreviousStates";
        private const string DATAPAGER_groupTotalPageCountKnown = "TotalPageCountKnownStates";
        private const string DATAPAGER_lastPageButtonAutomationId = "LargeIncrement";
        private const string DATAPAGER_nextPageButtonAutomationId = "SmallIncrement";
        private const string DATAPAGER_numericalButtonAutomationId = "MoveToPage";
        private const string DATAPAGER_previousPageButtonAutomationId = "SmallDecrement";
        private const string DATAPAGER_stateDisabled = "Disabled";
        private const string DATAPAGER_stateFirstLastNumeric = "FirstLastNumeric";
        private const string DATAPAGER_stateFirstLastPreviousNext = "FirstLastPreviousNext";
        private const string DATAPAGER_stateFirstLastPreviousNextNumeric = "FirstLastPreviousNextNumeric";
        private const string DATAPAGER_stateMoveDisabled = "MoveDisabled";
        private const string DATAPAGER_stateMoveEnabled = "MoveEnabled";
        private const string DATAPAGER_stateMoveFirstDisabled = "MoveFirstDisabled";
        private const string DATAPAGER_stateMoveFirstEnabled = "MoveFirstEnabled";
        private const string DATAPAGER_stateMoveLastDisabled = "MoveLastDisabled";
        private const string DATAPAGER_stateMoveLastEnabled = "MoveLastEnabled";
        private const string DATAPAGER_stateMoveNextDisabled = "MoveNextDisabled";
        private const string DATAPAGER_stateMoveNextEnabled = "MoveNextEnabled";
        private const string DATAPAGER_stateMovePreviousDisabled = "MovePreviousDisabled";
        private const string DATAPAGER_stateMovePreviousEnabled = "MovePreviousEnabled";
        private const string DATAPAGER_stateNormal = "Normal";
        private const string DATAPAGER_stateNumeric = "Numeric";
        private const string DATAPAGER_statePreviousNext = "PreviousNext";
        private const string DATAPAGER_statePreviousNextNumeric = "PreviousNextNumeric";
        private const string DATAPAGER_stateTotalPageCountKnown = "TotalPageCountKnown";
        private const string DATAPAGER_stateTotalPageCountUnknown = "TotalPageCountUnknown";
        private const string DATAPAGER_styleNumericButton = "NumericButtonStyle";
        public static readonly DependencyProperty DisplayModeProperty = DependencyProperty.Register("DisplayMode", typeof(PagerDisplayMode), typeof(DataPager), new PropertyMetadata(PagerDisplayMode.FirstLastPreviousNext, new PropertyChangedCallback(DataPager.OnDisplayModePropertyChanged)));
        public static readonly DependencyProperty IsTotalItemCountFixedProperty = DependencyProperty.Register("IsTotalItemCountFixed", typeof(bool), typeof(DataPager), new PropertyMetadata(true, new PropertyChangedCallback(DataPager.OnIsTotalItemCountFixedPropertyChanged)));
        public static readonly DependencyProperty ItemCountProperty = DependencyProperty.Register("ItemCount", typeof(int), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty NumericButtonCountProperty = DependencyProperty.Register("NumericButtonCount", typeof(int), typeof(DataPager), new PropertyMetadata(5, new PropertyChangedCallback(DataPager.OnNumericButtonCountPropertyChanged)));
        public static readonly DependencyProperty NumericButtonStyleProperty = DependencyProperty.Register("NumericButtonStyle", typeof(Style), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnNumericButtonStylePropertyChanged)));
        public static readonly DependencyProperty PageCountProperty = DependencyProperty.Register("PageCount", typeof(int), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnReadOnlyPropertyChanged)));
        public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register("PageIndex", typeof(int), typeof(DataPager), new PropertyMetadata(-1, new PropertyChangedCallback(DataPager.OnPageIndexPropertyChanged)));
        public static readonly DependencyProperty PageSizeProperty = DependencyProperty.Register("PageSize", typeof(int), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnPageSizePropertyChanged)));
        private static readonly DependencyProperty PrivateForegroundProperty = DependencyProperty.Register("PrivateForeground", typeof(Brush), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnPrivateForegroundPropertyChanged)));
        public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(IEnumerable), typeof(DataPager), new PropertyMetadata(new PropertyChangedCallback(DataPager.OnSourcePropertyChanged)));

        // Events
        public event EventHandler<EventArgs> PageIndexChanged;
        public event EventHandler<CancelEventArgs> PageIndexChanging;

        // Methods
        public DataPager()
        {
            base.DefaultStyleKey = typeof(DataPager);
            base.IsEnabledChanged += new DependencyPropertyChangedEventHandler(this.OnDataPagerIsEnabledChanged);
            Binding binding = new Binding().From<DataPager>(this, x => x.Foreground);
            base.SetBinding(PrivateForegroundProperty, binding);
        }

        private int GetButtonStartIndex()
        {
            return Math.Min(Math.Max((this.PageIndex + 1) - (this.NumericButtonCount / 2), 1), Math.Max((this.PageCount - this.NumericButtonCount) + 1, 1));
        }

        private void MoveCurrentPageToTextboxValue()
        {
            int num = this.PageIndex + 1;
            if (this._currentPageTextBox.Text != num.ToString(CultureInfo.CurrentCulture))
            {
                if ((this.PagedSource != null) && this.TryParseTextBoxPage())
                {
                    this.MoveToRequestedPage();
                }
                this._currentPageTextBox.Text = (this.PageIndex + 1).ToString(CultureInfo.CurrentCulture);
            }
        }

        private void MoveToRequestedPage()
        {
            if ((this._requestedPageIndex >= 0) && (this._requestedPageIndex < this.PageCount))
            {
                this.PageIndex = this._requestedPageIndex;
            }
            else if (this._requestedPageIndex >= this.PageCount)
            {
                if (this.IsTotalItemCountFixed && (this.PagedSource.TotalItemCount != -1))
                {
                    this.PageIndex = this.PageCount - 1;
                }
                else
                {
                    this.PageIndex = this._requestedPageIndex;
                }
            }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            if (this._firstPageButtonBase != null)
            {
                this._firstPageButtonBase.Click -= new RoutedEventHandler(this.OnFirstPageButtonBaseClick);
            }
            if (this._previousPageButtonBase != null)
            {
                this._previousPageButtonBase.Click -= new RoutedEventHandler(this.OnPreviousPageButtonBaseClick);
            }
            if (this._nextPageButtonBase != null)
            {
                this._nextPageButtonBase.Click -= new RoutedEventHandler(this.OnNextPageButtonBaseClick);
            }
            if (this._lastPageButtonBase != null)
            {
                this._lastPageButtonBase.Click -= new RoutedEventHandler(this.OnLastPageButtonBaseClick);
            }
            if (this._currentPageTextBox != null)
            {
                this._currentPageTextBox.KeyDown -= new KeyEventHandler(this.OnCurrentPageTextBoxKeyDown);
                this._currentPageTextBox.LostFocus -= new RoutedEventHandler(this.OnCurrentPageTextBoxLostFocus);
            }
            this._firstPageButtonBase = base.GetTemplateChild("FirstPageButton") as ButtonBase;
            this._previousPageButtonBase = base.GetTemplateChild("PreviousPageButton") as ButtonBase;
            this._nextPageButtonBase = base.GetTemplateChild("NextPageButton") as ButtonBase;
            this._lastPageButtonBase = base.GetTemplateChild("LastPageButton") as ButtonBase;
            if (this._firstPageButtonBase != null)
            {
                this._firstPageButtonBase.Click += new RoutedEventHandler(this.OnFirstPageButtonBaseClick);
                AutomationProperties.SetAutomationId(this._firstPageButtonBase, "LargeDecrement");
            }
            if (this._previousPageButtonBase != null)
            {
                this._previousPageButtonBase.Click += new RoutedEventHandler(this.OnPreviousPageButtonBaseClick);
                AutomationProperties.SetAutomationId(this._previousPageButtonBase, "SmallDecrement");
            }
            if (this._nextPageButtonBase != null)
            {
                this._nextPageButtonBase.Click += new RoutedEventHandler(this.OnNextPageButtonBaseClick);
                AutomationProperties.SetAutomationId(this._nextPageButtonBase, "SmallIncrement");
            }
            if (this._lastPageButtonBase != null)
            {
                this._lastPageButtonBase.Click += new RoutedEventHandler(this.OnLastPageButtonBaseClick);
                AutomationProperties.SetAutomationId(this._lastPageButtonBase, "LargeIncrement");
            }
            if (this._numericButtonPanel != null)
            {
                this._numericButtonPanel.Children.Clear();
            }
            this._numericButtonPanel = base.GetTemplateChild("NumericButtonPanel") as Panel;
            if (this._numericButtonPanel != null)
            {
                if (this._numericButtonPanel.Children.Count > 0)
                {
                    throw new InvalidOperationException("The NumericButtonPanel contains invalid children.");
                }
                this.UpdateButtonCount();
            }
            this._currentPageTextBox = base.GetTemplateChild("CurrentPageTextBox") as TextBox;
            this._currentPagePrefixTextBlock = base.GetTemplateChild("CurrentPagePrefixTextBlock") as TextBlock;
            this._currentPageSuffixTextBlock = base.GetTemplateChild("CurrentPageSuffixTextBlock") as TextBlock;
            if (this._currentPageTextBox != null)
            {
                this._currentPageTextBox.KeyDown += new KeyEventHandler(this.OnCurrentPageTextBoxKeyDown);
                this._currentPageTextBox.LostFocus += new RoutedEventHandler(this.OnCurrentPageTextBoxLostFocus);
                AutomationProperties.SetAutomationId(this._currentPageTextBox, "CurrentPage");
            }
            this.UpdateControl();
        }

        private static void OnAutoEllipsisPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataPager).UpdateButtonDisplay();
        }

        private void OnCurrentPageTextBoxKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                this.MoveCurrentPageToTextboxValue();
            }
        }

        private void OnCurrentPageTextBoxLostFocus(object sender, RoutedEventArgs e)
        {
            this.MoveCurrentPageToTextboxValue();
        }

        private void OnDataPagerIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            this.UpdateCommonState();
        }

        private static void OnDisplayModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if (!pager.AreHandlersSuspended())
            {
                if (!Enum.IsDefined(typeof(PagerDisplayMode), e.NewValue))
                {
                    pager.SetValueNoCallback(e.Property, e.OldValue);
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "The value of argument {0} ({1}) is invalid for Enum type {2}", new object[] { "value", e.NewValue.ToString(), typeof(PagerDisplayMode).Name }));
                }
                pager.UpdateControl();
            }
        }

        private void OnFirstPageButtonBaseClick(object sender, RoutedEventArgs e)
        {
            if (this.PagedSource != null)
            {
                int pageIndex = this.PagedSource.PageIndex;
                if (pageIndex != 0)
                {
                    IPagedCollectionView pagedSource = this.PagedSource;
                    this.PageMoveHandler(pageIndex, -1, new PageMoveOperationDelegate(pagedSource.MoveToFirstPage));
                }
            }
        }

        private static void OnIsTotalItemCountFixedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataPager).UpdateControl();
        }

        private void OnLastPageButtonBaseClick(object sender, RoutedEventArgs e)
        {
            if (this.PagedSource != null)
            {
                int pageIndex = this.PagedSource.PageIndex;
                if (pageIndex != this.PageCount)
                {
                    IPagedCollectionView pagedSource = this.PagedSource;
                    this.PageMoveHandler(pageIndex, -1, new PageMoveOperationDelegate(pagedSource.MoveToLastPage));
                }
            }
        }

        private void OnNextPageButtonBaseClick(object sender, RoutedEventArgs e)
        {
            if (this.PagedSource != null)
            {
                int pageIndex = this.PagedSource.PageIndex;
                if (pageIndex != (this.PageIndex + 1))
                {
                    IPagedCollectionView pagedSource = this.PagedSource;
                    this.PageMoveHandler(pageIndex, -1, new PageMoveOperationDelegate(pagedSource.MoveToNextPage));
                }
            }
        }

        private static void OnNumericButtonCountPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if (!pager.AreHandlersSuspended())
            {
                if (((int)e.NewValue) < 0)
                {
                    pager.SetValueNoCallback(e.Property, e.OldValue);
                    throw new ArgumentOutOfRangeException("value", string.Format(CultureInfo.InvariantCulture, "{0} must be greater than or equal to {1}.", new object[] { "NumericButtonCount", 0 }));
                }
                pager.UpdateButtonCount();
            }
        }

        private static void OnNumericButtonStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if (pager._numericButtonPanel != null)
            {
                foreach (UIElement element in pager._numericButtonPanel.Children)
                {
                    ToggleButton button = element as ToggleButton;
                    if (button != null)
                    {
                        button.Style = pager.NumericButtonStyle;
                    }
                }
                pager.UpdateNumericButtonsForeground();
            }
        }

        private static void OnPageIndexPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if (!pager.AreHandlersSuspended())
            {
                int newValue = (int)e.NewValue;
                if (((pager.Source == null) || (pager.PageSize == 0)) && (newValue != -1))
                {
                    pager.SetValueNoCallback(e.Property, e.OldValue);
                    throw new ArgumentOutOfRangeException("value", "The PageIndex property can only be set to -1 when the Source property is null or the PageSize property is 0.");
                }
                if (((pager.Source != null) && (pager.PageSize != 0)) && (newValue < 0))
                {
                    pager.SetValueNoCallback(e.Property, e.OldValue);
                    throw new ArgumentOutOfRangeException("value", string.Format(CultureInfo.InvariantCulture, "{0} must be greater than or equal to {1}.", new object[] { "PageIndex", 0 }));
                }
                if (pager.PagedSource != null)
                {
                    if (newValue != pager.PagedSource.PageIndex)
                    {
                        pager.PageMoveHandler((int)e.OldValue, newValue, null);
                    }
                }
                else if (pager.Source != null)
                {
                    if ((pager.PageSize != 0) && (newValue != 0))
                    {
                        pager.SetValueNoCallback(e.Property, e.OldValue);
                    }
                    else
                    {
                        pager.RaisePageIndexChangeEvents(true);
                    }
                }
                else if (newValue == -1)
                {
                    pager.RaisePageIndexChangeEvents(true);
                }
                else
                {
                    pager.SetValueNoCallback(e.Property, -1);
                }
            }
        }

        private static void OnPageSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if (pager.AreHandlersSuspended())
            {
                return;
            }
            int newValue = (int)e.NewValue;
            if (newValue < 0)
            {
                pager.SetValueNoCallback(e.Property, e.OldValue);
                throw new ArgumentOutOfRangeException("value", string.Format(CultureInfo.InvariantCulture, "{0} must be greater than or equal to {1}.", new object[] { "PageSize", 0 }));
            }
            if (pager.PagedSource != null)
            {
                try
                {
                    pager.PagedSource.PageSize = newValue;
                    goto Label_00B1;
                }
                catch
                {
                    pager.SetValueNoCallback(e.Property, e.OldValue);
                    throw;
                }
            }
            if (pager.Source != null)
            {
                pager.PageIndex = (pager.PageSize == 0) ? -1 : 0;
            }
        Label_00B1:
            pager.UpdateControl();
        }

        private void OnPreviousPageButtonBaseClick(object sender, RoutedEventArgs e)
        {
            if (this.PagedSource != null)
            {
                int pageIndex = this.PagedSource.PageIndex;
                if (pageIndex != (this.PageIndex - 1))
                {
                    IPagedCollectionView pagedSource = this.PagedSource;
                    this.PageMoveHandler(pageIndex, -1, new PageMoveOperationDelegate(pagedSource.MoveToPreviousPage));
                }
            }
        }

        private static void OnPrivateForegroundPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as DataPager).UpdateNumericButtonsForeground();
        }

        private static void OnReadOnlyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if ((pager != null) && !pager.AreHandlersSuspended())
            {
                pager.SetValueNoCallback(e.Property, e.OldValue);
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "{0} cannot be set because the underlying property is read only.", new object[] { e.Property.ToString() }));
            }
        }

        private void OnSourcePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "Count":
                case "ItemCount":
                    this.ItemCount = this.PagedSource.ItemCount;
                    this.UpdatePageCount();
                    this.UpdateControl();
                    return;

                case "PageIndex":
                    {
                        int pageIndex = this.PageIndex;
                        this.PageIndex = this.PagedSource.PageIndex;
                        this.RaisePageIndexChanged();
                        return;
                    }
                case "PageSize":
                    this.PageSize = this.PagedSource.PageSize;
                    this.UpdatePageCount();
                    this.UpdateControl();
                    return;

                case "CanChangePage":
                case "Filter":
                case "TotalItemCount":
                case "SortDescriptions":
                    this.UpdateControl();
                    return;
            }
        }

        private static void OnSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPager pager = d as DataPager;
            if ((e.OldValue is INotifyPropertyChanged) && (pager._weakEventListenerPropertyChanged != null))
            {
                pager._weakEventListenerPropertyChanged.Detach();
                pager._weakEventListenerPropertyChanged = null;
            }
            IPagedCollectionView newValue = e.NewValue as IPagedCollectionView;
            if (newValue != null)
            {
                Action<WeakEventListener<DataPager, object, PropertyChangedEventArgs>> action = null;
                INotifyPropertyChanged newNotifyPropertyChanged = e.NewValue as INotifyPropertyChanged;
                if (newNotifyPropertyChanged != null)
                {
                    pager._weakEventListenerPropertyChanged = new WeakEventListener<DataPager, object, PropertyChangedEventArgs>(pager);
                    pager._weakEventListenerPropertyChanged.OnEventAction = (instance, source, eventArgs) => instance.OnSourcePropertyChanged(source, eventArgs);
                    if (action == null)
                    {
                        action = delegate(WeakEventListener<DataPager, object, PropertyChangedEventArgs> weakEventListener)
                        {
                            newNotifyPropertyChanged.PropertyChanged -= new PropertyChangedEventHandler(weakEventListener.OnEvent);
                        };
                    }
                    pager._weakEventListenerPropertyChanged.OnDetachAction = action;
                    newNotifyPropertyChanged.PropertyChanged += new PropertyChangedEventHandler(pager._weakEventListenerPropertyChanged.OnEvent);
                }
                if (pager.PageSize != 0)
                {
                    newValue.PageSize = pager.PageSize;
                }
                else
                {
                    pager.PageSize = newValue.PageSize;
                }
                if (pager.PageIndex != newValue.PageIndex)
                {
                    if ((newValue.PageIndex == -1) && newValue.IsPageChanging)
                    {
                        pager.SetValueNoCallback(PageIndexProperty, -1);
                    }
                    else
                    {
                        pager.PageIndex = newValue.PageIndex;
                    }
                    pager.RaisePageIndexChangeEvents(true);
                }
                pager.ItemCount = newValue.ItemCount;
                pager.UpdatePageCount();
                if (newValue.IsPageChanging)
                {
                    pager.RaisePageIndexChangeEvents(false);
                }
            }
            else
            {
                IEnumerable enumerable = e.NewValue as IEnumerable;
                if (enumerable != null)
                {
                    pager.ItemCount = enumerable.Cast<object>().Count<object>();
                    pager.PageCount = 1;
                    pager.PageIndex = (pager.PageSize == 0) ? -1 : 0;
                }
                else
                {
                    pager.ItemCount = 0;
                    pager.PageCount = 0;
                    pager.PageIndex = -1;
                }
            }
            pager.UpdateControl();
        }

        private void PageMoveHandler(int oldPageIndex, int newPageIndex, PageMoveOperationDelegate pageMoveOperation)
        {
            CancelEventArgs e = new CancelEventArgs
            {
                Cancel = false
            };
            this.RaisePageIndexChanging(e);
            if (e.Cancel)
            {
                this.SetValueNoCallback(PageIndexProperty, oldPageIndex);
            }
            else
            {
                bool flag;
                if (pageMoveOperation == null)
                {
                    flag = this.PagedSource.MoveToPage(newPageIndex);
                }
                else
                {
                    flag = pageMoveOperation();
                }
                if (!flag)
                {
                    this.SetValueNoCallback(PageIndexProperty, oldPageIndex);
                    this.RaisePageIndexChanged();
                }
            }
        }

        private void RaisePageIndexChanged()
        {
            this.UpdateControl();
            if (this._needPageChangingNotification)
            {
                this.RaisePageIndexChangeEvents(false);
            }
            this._needPageChangingNotification = true;
            EventHandler<EventArgs> pageIndexChanged = this.PageIndexChanged;
            if (pageIndexChanged != null)
            {
                pageIndexChanged(this, EventArgs.Empty);
            }
        }

        private void RaisePageIndexChangeEvents(bool raisePageChanged)
        {
            CancelEventArgs e = new CancelEventArgs
            {
                Cancel = false
            };
            this.RaisePageIndexChanging(e);
            if (raisePageChanged)
            {
                this.RaisePageIndexChanged();
            }
        }

        private void RaisePageIndexChanging(CancelEventArgs e)
        {
            if (this._needPageChangingNotification)
            {
                EventHandler<CancelEventArgs> pageIndexChanging = this.PageIndexChanging;
                if (pageIndexChanging != null)
                {
                    pageIndexChanging(this, e);
                }
                if (!e.Cancel)
                {
                    this._needPageChangingNotification = false;
                }
            }
        }

        private void SetCanChangePage()
        {
            VisualStateManager.GoToState(this, "MoveEnabled", true);
            if (this._currentPageTextBox != null)
            {
                this._currentPageTextBox.Text = (this.PageIndex + 1).ToString(CultureInfo.CurrentCulture);
            }
        }

        private void SetCannotChangePage(bool needPage)
        {
            if ((this._currentPageTextBox != null) && !needPage)
            {
                this._currentPageTextBox.Text = string.Empty;
            }
            VisualStateManager.GoToState(this, "MoveDisabled", true);
            VisualStateManager.GoToState(this, "MoveFirstDisabled", true);
            VisualStateManager.GoToState(this, "MovePreviousDisabled", true);
            VisualStateManager.GoToState(this, "MoveNextDisabled", true);
            VisualStateManager.GoToState(this, "MoveLastDisabled", true);
        }

        private void ToggleButton_Checked(object sender, RoutedEventArgs e)
        {
            if (!this._ignoreToggleButtonCheckedNotification && (this.PagedSource != null))
            {
                ToggleButton button = sender as ToggleButton;
                int index = this._numericButtonPanel.Children.IndexOf(button);
                int newPageIndex = (this.GetButtonStartIndex() + index) - 1;
                this.PageMoveHandler(this.PageIndex, newPageIndex, null);
                if (this.PagedSource.PageIndex != newPageIndex)
                {
                    try
                    {
                        this._ignoreToggleButtonUncheckedNotification = true;
                        button.IsChecked = false;
                    }
                    finally
                    {
                        this._ignoreToggleButtonUncheckedNotification = false;
                    }
                }
            }
        }

        private void ToggleButton_GotFocus(object sender, RoutedEventArgs e)
        {
            if (!this._ignoreToggleButtonFocusNotification)
            {
                ToggleButton button = sender as ToggleButton;
                int index = this._numericButtonPanel.Children.IndexOf(button);
                this._focusedToggleButtonIndex = (this.GetButtonStartIndex() + index) - 1;
            }
        }

        private void ToggleButton_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!this._ignoreToggleButtonFocusNotification)
            {
                this._focusedToggleButtonIndex = -1;
            }
        }

        private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (!this._ignoreToggleButtonUncheckedNotification)
            {
                try
                {
                    this._ignoreToggleButtonCheckedNotification = true;
                    ToggleButton button = sender as ToggleButton;
                    button.IsChecked = true;
                }
                finally
                {
                    this._ignoreToggleButtonCheckedNotification = false;
                }
            }
        }

        private bool TryParseTextBoxPage()
        {
            bool flag = int.TryParse(this._currentPageTextBox.Text, NumberStyles.Integer, CultureInfo.InvariantCulture, out this._requestedPageIndex);
            if (flag)
            {
                this._requestedPageIndex--;
            }
            return flag;
        }

        private void UpdateButtonCount()
        {
            int num = Math.Min(this.NumericButtonCount, this.PageCount);
            if (this._numericButtonPanel != null)
            {
                while (this._numericButtonPanel.Children.Count < num)
                {
                    ToggleButton button = new ToggleButton
                    {
                        Style = this.NumericButtonStyle
                    };
                    button.Checked += new RoutedEventHandler(this.ToggleButton_Checked);
                    button.Unchecked += new RoutedEventHandler(this.ToggleButton_Unchecked);
                    button.GotFocus += new RoutedEventHandler(this.ToggleButton_GotFocus);
                    button.LostFocus += new RoutedEventHandler(this.ToggleButton_LostFocus);
                    this._numericButtonPanel.Children.Add(button);
                }
                while (this._numericButtonPanel.Children.Count > num)
                {
                    ToggleButton button2 = this._numericButtonPanel.Children[0] as ToggleButton;
                    if (button2 != null)
                    {
                        button2.Checked -= new RoutedEventHandler(this.ToggleButton_Checked);
                        button2.Unchecked -= new RoutedEventHandler(this.ToggleButton_Unchecked);
                        button2.GotFocus -= new RoutedEventHandler(this.ToggleButton_GotFocus);
                        button2.LostFocus -= new RoutedEventHandler(this.ToggleButton_LostFocus);
                        this._numericButtonPanel.Children.Remove(button2);
                    }
                }
                this.UpdateNumericButtonsForeground();
                this.UpdateButtonDisplay();
            }
        }

        private void UpdateButtonDisplay()
        {
            if (this._numericButtonPanel != null)
            {
                int buttonStartIndex = this.GetButtonStartIndex();
                int num2 = Math.Min(this.NumericButtonCount, this.PageCount);
                bool flag = false;
                int num3 = buttonStartIndex;
                foreach (UIElement element in this._numericButtonPanel.Children)
                {
                    ToggleButton button = element as ToggleButton;
                    if (button == null)
                    {
                        continue;
                    }
                    if (this.PagedSource == null)
                    {
                        button.IsChecked = true;
                    }
                    else
                    {
                        if ((this.PagedSource != null) && (this.PagedSource.PageIndex == (num3 - 1)))
                        {
                            try
                            {
                                this._ignoreToggleButtonCheckedNotification = true;
                                button.IsChecked = true;
                                goto Label_00D5;
                            }
                            finally
                            {
                                this._ignoreToggleButtonCheckedNotification = false;
                            }
                        }
                        if (button.IsChecked.Value)
                        {
                            try
                            {
                                this._ignoreToggleButtonUncheckedNotification = true;
                                button.IsChecked = false;
                            }
                            finally
                            {
                                this._ignoreToggleButtonUncheckedNotification = false;
                            }
                        }
                    }
                Label_00D5:
                    if ((this.AutoEllipsis && (num3 == ((buttonStartIndex + num2) - 1))) && (num3 != this.PageCount))
                    {
                        button.Content = "...";
                    }
                    else
                    {
                        button.Content = num3;
                    }
                    if ((this._focusedToggleButtonIndex != -1) && (this._focusedToggleButtonIndex == (num3 - 1)))
                    {
                        try
                        {
                            this._ignoreToggleButtonFocusNotification = true;
                            button.Focus();
                        }
                        finally
                        {
                            this._ignoreToggleButtonFocusNotification = false;
                        }
                        flag = true;
                    }
                    AutomationProperties.SetAutomationId(button, "MoveToPage" + num3.ToString(CultureInfo.CurrentCulture));
                    num3++;
                }
                if ((this._focusedToggleButtonIndex != -1) && !flag)
                {
                    foreach (UIElement element2 in this._numericButtonPanel.Children)
                    {
                        ToggleButton button2 = element2 as ToggleButton;
                        if ((button2 != null) && button2.IsChecked.Value)
                        {
                            button2.Focus();
                            break;
                        }
                    }
                }
            }
        }

        private void UpdateCanPageFirstAndPrevious()
        {
            VisualStateManager.GoToState(this, this.CanMoveToFirstPage ? "MoveFirstEnabled" : "MoveFirstDisabled", true);
            VisualStateManager.GoToState(this, this.CanMoveToPreviousPage ? "MovePreviousEnabled" : "MovePreviousDisabled", true);
        }

        private void UpdateCanPageNextAndLast()
        {
            VisualStateManager.GoToState(this, this.CanMoveToNextPage ? "MoveNextEnabled" : "MoveNextDisabled", true);
            VisualStateManager.GoToState(this, this.CanMoveToLastPage ? "MoveLastEnabled" : "MoveLastDisabled", true);
        }

        private void UpdateCommonState()
        {
            VisualStateManager.GoToState(this, base.IsEnabled ? "Normal" : "Disabled", true);
        }

        private void UpdateControl()
        {
            this.UpdatePageModeDisplay();
            this.UpdateButtonCount();
            bool needPage = (this.Source != null) && (((this.PagedSource == null) && (this.PageSize > 0)) || ((this.PagedSource != null) && (this.PagedSource.PageSize > 0)));
            this.CanMoveToFirstPage = needPage && (this.PageIndex > 0);
            this.CanMoveToPreviousPage = this.CanMoveToFirstPage;
            this.CanMoveToNextPage = (needPage && (this.PagedSource != null)) && ((!this.IsTotalItemCountFixed || (this.PagedSource.TotalItemCount == -1)) || (this.PageIndex < (this.PageCount - 1)));
            this.CanMoveToLastPage = ((needPage && (this.PagedSource != null)) && (this.PagedSource.TotalItemCount != -1)) && (this.PageIndex < (this.PageCount - 1));
            this.CanChangePage = needPage && ((this.PagedSource == null) || this.PagedSource.CanChangePage);
            this.UpdateCurrentPagePrefixAndSuffix(needPage);
            if (!needPage || !this.CanChangePage)
            {
                this.SetCannotChangePage(needPage);
            }
            else
            {
                this.SetCanChangePage();
                this.UpdateCanPageFirstAndPrevious();
                this.UpdateCanPageNextAndLast();
            }
        }

        private void UpdateCurrentPagePrefixAndSuffix(bool needPage)
        {
            string str;
            bool flag = !needPage || ((this.PagedSource != null) && (this.PagedSource.TotalItemCount == -1));
            if ((this._currentPagePrefixTextBlock != null) && (this._currentPagePrefixTextBlock != null))
            {
                if (flag)
                {
                    str = "Page";
                }
                else
                {
                    str = string.Format(CultureInfo.InvariantCulture, "Page", new object[] { this.PageCount.ToString(CultureInfo.CurrentCulture) });
                }
                this._currentPagePrefixTextBlock.Text = str;
                if (string.IsNullOrEmpty(str))
                {
                    this._currentPagePrefixTextBlock.Visibility = Visibility.Collapsed;
                }
                else
                {
                    this._currentPagePrefixTextBlock.Visibility = Visibility.Visible;
                }
            }
            if (this._currentPageSuffixTextBlock != null)
            {
                if (flag)
                {
                    str = "";
                }
                else
                {
                    str = string.Format(CultureInfo.InvariantCulture, "", new object[] { this.PageCount.ToString(CultureInfo.CurrentCulture) });
                }
                this._currentPageSuffixTextBlock.Text = str;
                if (string.IsNullOrEmpty(str))
                {
                    this._currentPageSuffixTextBlock.Visibility = Visibility.Collapsed;
                }
                else
                {
                    this._currentPageSuffixTextBlock.Visibility = Visibility.Visible;
                }
            }
            VisualStateManager.GoToState(this, flag ? "TotalPageCountUnknown" : "TotalPageCountKnown", true);
        }

        private void UpdateNumericButtonsForeground()
        {
            if (this._numericButtonPanel != null)
            {
                foreach (UIElement element in this._numericButtonPanel.Children)
                {
                    ToggleButton button = element as ToggleButton;
                    if (button != null)
                    {
                        bool flag = true;
                        if (button.Style != null)
                        {
                            foreach (SetterBase base2 in button.Style.Setters)
                            {
                                Setter setter = base2 as Setter;
                                if (((setter != null) && (setter.Property != null)) && (setter.Property.Equals(Control.ForegroundProperty) && (setter.Value != null)))
                                {
                                    flag = false;
                                    break;
                                }
                            }
                        }
                        if (flag)
                        {
                            button.Foreground = base.Foreground;
                        }
                    }
                }
            }
        }

        private void UpdatePageCount()
        {
            if (this.PagedSource.PageSize > 0)
            {
                this.PageCount = Math.Max(1, (int)Math.Ceiling((double)(((double)this.PagedSource.ItemCount) / ((double)this.PagedSource.PageSize))));
            }
            else
            {
                this.PageCount = 1;
            }
        }

        private void UpdatePageModeDisplay()
        {
            VisualStateManager.GoToState(this, Enum.GetName(typeof(PagerDisplayMode), this.DisplayMode), true);
        }

        // Properties
        public bool AutoEllipsis
        {
            get
            {
                return (bool)base.GetValue(AutoEllipsisProperty);
            }
            set
            {
                base.SetValue(AutoEllipsisProperty, value);
            }
        }

        public bool CanChangePage
        {
            get
            {
                return (bool)base.GetValue(CanChangePageProperty);
            }
            private set
            {
                this.SetValueNoCallback(CanChangePageProperty, value);
            }
        }

        public bool CanMoveToFirstPage
        {
            get
            {
                return (bool)base.GetValue(CanMoveToFirstPageProperty);
            }
            private set
            {
                this.SetValueNoCallback(CanMoveToFirstPageProperty, value);
            }
        }

        public bool CanMoveToLastPage
        {
            get
            {
                return (bool)base.GetValue(CanMoveToLastPageProperty);
            }
            private set
            {
                this.SetValueNoCallback(CanMoveToLastPageProperty, value);
            }
        }

        public bool CanMoveToNextPage
        {
            get
            {
                return (bool)base.GetValue(CanMoveToNextPageProperty);
            }
            private set
            {
                this.SetValueNoCallback(CanMoveToNextPageProperty, value);
            }
        }

        public bool CanMoveToPreviousPage
        {
            get
            {
                return (bool)base.GetValue(CanMoveToPreviousPageProperty);
            }
            private set
            {
                this.SetValueNoCallback(CanMoveToPreviousPageProperty, value);
            }
        }

        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)base.GetValue(CornerRadiusProperty);
            }
            set
            {
                base.SetValue(CornerRadiusProperty, value);
            }
        }

        internal TextBox CurrentPageTextBox
        {
            get
            {
                return this._currentPageTextBox;
            }
        }

        public PagerDisplayMode DisplayMode
        {
            get
            {
                return (PagerDisplayMode)base.GetValue(DisplayModeProperty);
            }
            set
            {
                base.SetValue(DisplayModeProperty, value);
            }
        }

        public bool IsTotalItemCountFixed
        {
            get
            {
                return (bool)base.GetValue(IsTotalItemCountFixedProperty);
            }
            set
            {
                base.SetValue(IsTotalItemCountFixedProperty, value);
            }
        }

        public int ItemCount
        {
            get
            {
                return (int)base.GetValue(ItemCountProperty);
            }
            private set
            {
                this.SetValueNoCallback(ItemCountProperty, value);
            }
        }

        public int NumericButtonCount
        {
            get
            {
                return (int)base.GetValue(NumericButtonCountProperty);
            }
            set
            {
                base.SetValue(NumericButtonCountProperty, value);
            }
        }

        public Style NumericButtonStyle
        {
            get
            {
                return (Style)base.GetValue(NumericButtonStyleProperty);
            }
            set
            {
                base.SetValue(NumericButtonStyleProperty, value);
            }
        }

        public int PageCount
        {
            get
            {
                return (int)base.GetValue(PageCountProperty);
            }
            private set
            {
                this.SetValueNoCallback(PageCountProperty, value);
            }
        }

        internal IPagedCollectionView PagedSource
        {
            get
            {
                return (this.Source as IPagedCollectionView);
            }
        }

        [DefaultValue(-1)]
        public int PageIndex
        {
            get
            {
                return (int)base.GetValue(PageIndexProperty);
            }
            set
            {
                base.SetValue(PageIndexProperty, value);
            }
        }

        public int PageSize
        {
            get
            {
                return (int)base.GetValue(PageSizeProperty);
            }
            set
            {
                base.SetValue(PageSizeProperty, value);
            }
        }

        private Brush PrivateForeground
        {
            get
            {
                return (base.GetValue(PrivateForegroundProperty) as Brush);
            }
            set
            {
                base.SetValue(PrivateForegroundProperty, value);
            }
        }

        public IEnumerable Source
        {
            get
            {
                return (base.GetValue(SourceProperty) as IEnumerable);
            }
            set
            {
                base.SetValue(SourceProperty, value);
            }
        }

        // Nested Types
        private delegate bool PageMoveOperationDelegate();
    }
}
